--[[
  机器人库存管理服务
  主要管理机器人的金钱，机器人从此处取钱和存钱
]]

local skynet = require "skynet"
local cluster = require "skynet.cluster"
local filename = "inventorymgr.lua"
local filelog = require "filelog"
local queue = require "skynet.queue"
local tabletool = require "tabletool"
require "skynet.manager"
require "pubenum"

local cs = queue()

local InventoryMgr = {
    CMD = {},
    handler = {},
    money = {
        diamond = 0,
        coin = 0,
    },
}

--库存对应的rid
local Inventory_rids = {
    diamond = 99,
    coin = 100,
}

--------------------------------

--[Comment]
-- 初始化
-- 库存保存在rs_robot中，rid = 99表示diamond rid = 100表示coin
--
function InventoryMgr.init()
    for moneytype,rid in pairs(Inventory_rids) do
        local status,result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_robot")
        if status and result and result[1] ~= 0 and result[2] then
            local value = tonumber(result[2][rid].cpass) or 0
            InventoryMgr.money[moneytype] = value
        end
    end
end

--[Comment]
-- 获得库存值
--
function InventoryMgr.handler.get_inventory(moneytype)
    moneytype = moneytype or "diamond"
    return (InventoryMgr.money[moneytype] or 0)
end

--[Comment]
-- 修改库存值
--
function InventoryMgr.handler.update_inventory(moneytype, value)
    --实际修改函数
    local function real_update_inventory(moneytype, value)
        local sys_inventory = 0
        local rid = Inventory_rids[moneytype]
        local status,result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_robot", true)
        if status and result and result[1] ~= 0 then
            sys_inventory = tonumber(result[2][rid].cpass) or 0
        end

        --更新库存
        local beginvalue = sys_inventory
        local endvalue = sys_inventory + value
        if endvalue >= 0 and beginvalue ~= endvalue then
            skynet.pcall(cluster.call, "datanode", ".router", "update_rk", rid, "rs_robot", 0, {cpass = tostring(endvalue)})
            InventoryMgr.money[moneytype] = endvalue
        elseif endvalue < 0 then
            return false
        end
            
        return endvalue
    end

    --修改
    if not Inventory_rids[moneytype] then
        return false
    end

    return cs(real_update_inventory, moneytype, value) 
end

---------------

--[Comment]
-- 机器人取钱
-- rid 机器人角色rid
-- moneytype 金钱类型 diamond金豆 coin金币
-- initmoney 初始金钱数
-- moneynum 取钱数目
-- gamename 所在游戏名
--
function InventoryMgr.CMD.draw_money(rid, moneytype, initmoney, moneynum, gamename)
    if moneytype ~= "diamond" and moneytype ~= "coin" then
        return
    end

    if gamename == "" then
        gamename = nil
    end

    moneynum = tonumber(moneynum) or 0
    if moneynum > 0 then
        local curmoney = InventoryMgr.handler.get_inventory(moneytype)
        if curmoney < moneynum then
            filelog.sys_error("InventoryMgr.CMD.draw_money: not enough money!", rid, curmoney, moneynum)
            return false
        end

        --修改库存
        local endmoney = InventoryMgr.handler.update_inventory(moneytype, -moneynum)
        if not endmoney then
            filelog.sys_error("InventoryMgr.CMD.draw_money: change inventory failed!", rid, curmoney, moneytype, -moneynum)
            return false
        end

        --给玩家加钱
        local status,result = skynet.pcall(cluster.call, "gatenode", ".router", "change_money", rid, {[moneytype] = moneynum}, {})
        if status and result then
            local logname = ("." .. moneytype .. "log")
            --变化原因（1取钱 2存钱），金钱池id，机器人rid，变化金豆数，初始金豆，结束金豆，变化库存，初始库存，结束库存，游戏名，交易id
            local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", 1, Inventory_rids[moneytype], rid, moneynum, initmoney, initmoney+moneynum, -moneynum, curmoney, endmoney, gamename, nil)
            skynet.send(logname, "lua", "write", logstr)
            return true
        else
            InventoryMgr.handler.update_inventory(moneytype, moneynum)
            filelog.sys_error("InventoryMgr.CMD.draw_money: call change_money failed!", rid, status, result)
            return false
        end
    end
    
    return true
end

--[Comment]
-- 机器人存钱
-- rid 机器人角色rid
-- moneytype 金钱类型 diamond金豆 coin金币
-- initmoney 初始金钱数
-- moneynum 保存金钱数
-- gamename 所在游戏名
--
function InventoryMgr.CMD.save_money(rid, moneytype, initmoney, moneynum, gamename)
    if moneytype ~= "diamond" and moneytype ~= "coin" then
        return
    end

    --金豆再去数据库拉取一次,避免数据失效
    if moneytype == "diamond" then
        local status,result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rs_money", true)
        if status and result and result[1] ~= 0 then
            local diamond = tonumber(result[2][rid].diamond) or 0
            if moneynum > diamond then
                moneynum = diamond
            end
        else
            filelog.sys_error("InventoryMgr.CMD.save_money: get money data failed!", rid, status, result)
            return false
        end
    end

    if gamename == "" then
        gamename = nil
    end

    moneynum = tonumber(moneynum) or 0
    if moneynum > 0 then
        --给玩家减钱
        local status,result = skynet.pcall(cluster.call, "gatenode", ".router", "change_money", rid, {[moneytype] = -moneynum}, {})
        if not status or not result then
            filelog.sys_error("InventoryMgr.CMD.save_money: call change_money failed!", rid, status, result)
            return false
        end

        --修改库存
        local logname = ("." .. moneytype .. "log")
        local curmoney = InventoryMgr.handler.get_inventory(moneytype)
        local endmoney = InventoryMgr.handler.update_inventory(moneytype, moneynum)
        --变化原因（1取钱 2存钱），金钱池id，机器人rid，变化金豆数，初始金豆，结束金豆，变化库存，初始库存，结束库存，游戏名，交易id
        local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", 2, Inventory_rids[moneytype], rid, moneynum-initmoney, initmoney, moneynum, moneynum, curmoney, endmoney, gamename, nil)
        skynet.send(logname, "lua", "write", logstr)
    end

    return true
end

--[Comment]
-- gm后台增加库存
-- moneytype 金钱类型 diamond金豆 coin金币
-- value 增加值
-- reason 操作原因 0 GM增加
--
function InventoryMgr.CMD.add_inventory(moneytype, value, reason)
    local rid = Inventory_rids[moneytype]
    local beginvalue = InventoryMgr.money[moneytype] or 0
    local result = InventoryMgr.handler.update_inventory(moneytype, value)
    if result then
        local logname = ("." .. moneytype .. "log")
        local endvalue = InventoryMgr.money[moneytype] or 0
        local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", 3, rid, 0, value, 0, 0, beginvalue, endvalue, 0, reason, "GM")
        skynet.send(logname, "lua", "write", logstr)
    end
end

--[Comment]
-- gm后台减少库存
-- moneytype 金钱类型 diamond金豆 coin金币
-- value 减少值
-- reason 操作原因 0 GM减少
--
function InventoryMgr.CMD.sub_inventory(moneytype, value, reason)
    local rid = Inventory_rids[moneytype]
    local beginvalue = InventoryMgr.money[moneytype] or 0
    local result = InventoryMgr.handler.update_inventory(moneytype, -value)
    if result then
        local logname = ("." .. moneytype .. "log")
        local endvalue = InventoryMgr.money[moneytype] or 0
        local logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s", 4, rid, 0, -value, 0, 0, beginvalue, endvalue, 0, reason, "GM")
        skynet.send(logname, "lua", "write", logstr)
    end
end

--[Comment]
-- 获得机器人库存
--
function InventoryMgr.CMD.get_robot_inventory()
    local moneys = tabletool.deepcopy(InventoryMgr.money) or {}
    return moneys
end

-----------

skynet.start(function()
    skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = InventoryMgr.CMD[cmd]
        if f then
            skynet.retpack(f(...))
        else
            skynet.retpack()
        end
    end)
    InventoryMgr.init()
end)